home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_008 / src / hack.dog.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  394 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* hack.dog.c version 1.0.1 - "You feel worried about %s." (Adri Verhoef) */
  3.  
  4. #include    "hack.h"
  5. #include    "hack.mfndpos.h"
  6. extern char POISONOUS[];
  7. extern struct monst *makemon();
  8. #include "def.edog.h"
  9.  
  10. makedog(){
  11. register struct monst *mtmp = makemon(PM_LI_DOG,u.ux,u.uy);
  12.     if(!mtmp) return; /* dogs were genocided */
  13.     initedog(mtmp);
  14. }
  15.  
  16. initedog(mtmp) register struct monst *mtmp; {
  17.     mtmp->mtame = mtmp->mpeaceful = 1;
  18.     EDOG(mtmp)->hungrytime = 1000 + moves;
  19.     EDOG(mtmp)->eattime = 0;
  20.     EDOG(mtmp)->droptime = 0;
  21.     EDOG(mtmp)->dropdist = 10000;
  22.     EDOG(mtmp)->apport = 10;
  23.     EDOG(mtmp)->whistletime = 0;
  24. }
  25.  
  26. /* attach the monsters that went down (or up) together with @ */
  27. struct monst *mydogs = 0;
  28. struct monst *fallen_down = 0;    /* monsters that fell through a trapdoor */
  29.  
  30. losedogs(){
  31. register struct monst *mtmp;
  32.     while(mtmp = mydogs){
  33.         mydogs = mtmp->nmon;
  34.         mtmp->nmon = fmon;
  35.         fmon = mtmp;
  36.         mnexto(mtmp);
  37.     }
  38.     while(mtmp = fallen_down){
  39.         fallen_down = mtmp->nmon;
  40.         mtmp->nmon = fmon;
  41.         fmon = mtmp;
  42.         rloc(mtmp);
  43.     }
  44. }
  45.  
  46. keepdogs(){
  47. register struct monst *mtmp;
  48.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->mtame) {
  49.         if(dist(mtmp->mx,mtmp->my) > 2) {
  50.             mtmp->mtame = 0;    /* dog becomes wild */
  51.             mtmp->mpeaceful = 0;
  52.             continue;
  53.         }
  54.         relmon(mtmp);
  55.         mtmp->nmon = mydogs;
  56.         mydogs = mtmp;
  57.         unpmon(mtmp);
  58.         keepdogs();    /* we destroyed the link, so use recursion */
  59.         return;        /* (admittedly somewhat primitive) */
  60.     }
  61. }
  62.  
  63. fall_down(mtmp) register struct monst *mtmp; {
  64.     relmon(mtmp);
  65.     mtmp->nmon = fallen_down;
  66.     fallen_down = mtmp;
  67.     unpmon(mtmp);
  68.     mtmp->mtame = 0;
  69. }
  70.  
  71. /* return quality of food; the lower the better */
  72. #define    DOGFOOD    0
  73. #define    CADAVER    1
  74. #define    ACCFOOD    2
  75. #define    MANFOOD    3
  76. #define    APPORT    4
  77. #define    POISON    5
  78. #define    UNDEF    6
  79. dogfood(obj) register struct obj *obj; {
  80.     switch(obj->olet) {
  81.     case FOOD_SYM:
  82.         return(
  83.         (obj->otyp == TRIPE_RATION) ? DOGFOOD :
  84.         (obj->otyp < CARROT) ? ACCFOOD :
  85.         (obj->otyp < CORPSE) ? MANFOOD :
  86.         (index(POISONOUS, obj->spe) || obj->age + 50 <= moves ||
  87.             obj->otyp == DEAD_COCKATRICE)
  88.             ? POISON : CADAVER
  89.         );
  90.     default:
  91.         if(!obj->cursed) return(APPORT);
  92.         /* fall into next case */
  93.     case BALL_SYM:
  94.     case CHAIN_SYM:
  95.     case ROCK_SYM:
  96.         return(UNDEF);
  97.     }
  98. }
  99.  
  100. /* return 0 (no move), 1 (move) or 2 (dead) */
  101. dog_move(mtmp, after) register struct monst *mtmp; {
  102. register int nx,ny,omx,omy,appr,nearer,j;
  103. int udist,chi,i,whappr;
  104. register struct monst *mtmp2;
  105. register struct permonst *mdat = mtmp->data;
  106. register struct edog *edog = EDOG(mtmp);
  107. struct obj *obj;
  108. struct gen *trap;
  109. xchar cnt,chcnt,nix,niy;
  110. schar dogroom,uroom;
  111. xchar gx,gy,gtyp,otyp;    /* current goal */
  112. coord poss[9];
  113. int info[9];
  114. #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
  115. #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
  116.  
  117.     if(moves <= edog->eattime) return(0);    /* dog is still eating */
  118.     omx = mtmp->mx;
  119.     omy = mtmp->my;
  120.     whappr = (moves - EDOG(mtmp)->whistletime < 5);
  121.     if(moves > edog->hungrytime + 500 && !mtmp->mconf){
  122.         mtmp->mconf = 1;
  123.         mtmp->orig_hp /= 3;
  124.         if(mtmp->mhp > mtmp->orig_hp)
  125.             mtmp->mhp = mtmp->orig_hp;
  126.         if(cansee(omx,omy))
  127.             pline("%s is confused from hunger", Monnam(mtmp));
  128.         else    pline("You feel worried about %s.", monnam(mtmp));
  129.     } else
  130.     if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){
  131.         if(cansee(omx,omy))
  132.             pline("%s dies from hunger", Monnam(mtmp));
  133.         else
  134.         pline("You have a sad feeling for a moment, then it passes");
  135.         mondied(mtmp);
  136.         return(2);
  137.     }
  138.     dogroom = inroom(omx,omy);
  139.     uroom = inroom(u.ux,u.uy);
  140.     udist = dist(omx,omy);
  141.  
  142.     /* if we are carrying sth then we drop it (perhaps near @) */
  143.     /* Note: if apport == 1 then our behaviour is independent of udist */
  144.     if(mtmp->minvent){
  145.         if(!rn2(udist) || !rn2((int) edog->apport))
  146.         if(rn2(10) < edog->apport){
  147.             relobj(mtmp,0);
  148.             if(edog->apport > 1) edog->apport--;
  149.         }
  150.     } else {
  151.         if(obj = o_at(omx,omy)) if(!index("0_", obj->olet)){
  152.             if((otyp = dogfood(obj)) <= CADAVER){
  153.             nix = omx;
  154.             niy = omy;
  155.             goto eatobj;
  156.             }
  157.             if(obj->owt < 10*mtmp->data->mlevel)
  158.             if(rn2(20) < edog->apport+3)
  159.             if(rn2(udist) || !rn2((int) edog->apport)){
  160.             freeobj(obj);
  161.             unpobj(obj);
  162.             /* if(levl[omx][omy].scrsym == obj->olet)
  163.                 newsym(omx,omy); */
  164.             mpickobj(mtmp,obj);
  165.             }
  166.         }
  167.     }
  168.  
  169.     /* first we look for food */
  170.     gtyp = UNDEF;    /* no goal as yet */
  171. #ifdef LINT
  172.     gx = gy = 0;
  173. #endif LINT
  174.     for(obj = fobj; obj; obj = obj->nobj) {
  175.         otyp = dogfood(obj);
  176.         if(otyp > gtyp || otyp == UNDEF) continue;
  177.         if(inroom(obj->ox,obj->oy) != dogroom) continue;
  178.         if(otyp < MANFOOD &&
  179.          (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
  180.             if(otyp < gtyp || (otyp == gtyp &&
  181.                 DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
  182.                 gx = obj->ox;
  183.                 gy = obj->oy;
  184.                 gtyp = otyp;
  185.             }
  186.         } else
  187.         if(gtyp == UNDEF && dogroom >= 0 &&
  188.            uroom == dogroom &&
  189.            !mtmp->minvent && edog->apport > rn2(8)){
  190.             gx = obj->ox;
  191.             gy = obj->oy;
  192.             gtyp = APPORT;
  193.         }
  194.     }
  195.     if(gtyp == UNDEF ||
  196.       (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){
  197.         if(dogroom < 0 || dogroom == uroom){
  198.             gx = u.ux;
  199.             gy = u.uy;
  200. #ifndef QUEST
  201.         } else {
  202.             int tmp = rooms[dogroom].fdoor;
  203.                 cnt = rooms[dogroom].doorct;
  204.  
  205.             gx = gy = FAR;    /* random, far away */
  206.             while(cnt--){
  207.                 if(dist(gx,gy) >
  208.                 dist(doors[tmp].x, doors[tmp].y)){
  209.                     gx = doors[tmp].x;
  210.                     gy = doors[tmp].y;
  211.                 }
  212.                 tmp++;
  213.             }
  214.             /* here gx == FAR e.g. when dog is in a vault */
  215.             if(gx == FAR || (gx == omx && gy == omy)){
  216.                 gx = u.ux;
  217.                 gy = u.uy;
  218.             }
  219. #endif QUEST
  220.         }
  221.         appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
  222.         if(after && udist <= 4 && gx == u.ux && gy == u.uy)
  223.             return(0);
  224.         if(udist > 1){
  225.             if(levl[u.ux][u.uy].typ < ROOM || !rn2(4) ||
  226.                whappr ||
  227.                (mtmp->minvent && rn2((int) edog->apport)))
  228.                 appr = 1;
  229.         }
  230.         /* if you have dog food he'll follow you more closely */
  231.         if(appr == 0){
  232.             obj = invent;
  233.             while(obj){
  234.                 if(obj->otyp == TRIPE_RATION){
  235.                     appr = 1;
  236.                     break;
  237.                 }
  238.                 obj = obj->nobj;
  239.             }
  240.         }
  241.     } else    appr = 1;    /* gtyp != UNDEF */
  242.     if(mtmp->mconf) appr = 0;
  243. #ifdef TRACK
  244.     if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){
  245.     extern coord *gettrack();
  246.     register coord *cp;
  247.         cp = gettrack(omx,omy);
  248.         if(cp){
  249.             gx = cp->x;
  250.             gy = cp->y;
  251.         }
  252.     }
  253. #endif TRACK
  254.     nix = omx;
  255.     niy = omy;
  256.     cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS);
  257.     chcnt = 0;
  258.     chi = -1;
  259.     for(i=0; i<cnt; i++){
  260.         nx = poss[i].x;
  261.         ny = poss[i].y;
  262.         if(info[i] & ALLOW_M){
  263.             mtmp2 = m_at(nx,ny);
  264.             if(mtmp2->data->mlevel >= mdat->mlevel+2 ||
  265.               mtmp2->data->mlet == 'c')
  266.                 continue;
  267.             if(after) return(0); /* hit only once each move */
  268.  
  269.             if(hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
  270.               mtmp2->mlstmv != moves &&
  271.               hitmm(mtmp2,mtmp) == 2) return(2);
  272.             return(0);
  273.         }
  274.  
  275.         /* dog avoids traps */
  276.         /* but perhaps we have to pass a trap in order to follow @ */
  277.         if((info[i] & ALLOW_TRAPS) && (trap = g_at(nx,ny,ftrap))){
  278.             if(!(trap->gflag & SEEN) && rn2(40)) continue;
  279.             if(rn2(10)) continue;
  280.         }
  281.  
  282.         /* dog eschewes cursed objects */
  283.         /* but likes dog food */
  284.         obj = fobj;
  285.         while(obj){
  286.             if(obj->ox != nx || obj->oy != ny)
  287.             goto nextobj;
  288.             if(obj->cursed) goto nxti;
  289.             if(obj->olet == FOOD_SYM &&
  290.             (otyp = dogfood(obj)) < MANFOOD &&
  291.             (otyp < ACCFOOD || edog->hungrytime <= moves)){
  292.             /* Note: our dog likes the food so much that he
  293.             might eat it even when it conceals a cursed object */
  294.             nix = nx;
  295.             niy = ny;
  296.             chi = i;
  297.              eatobj:
  298.             edog->eattime =
  299.                 moves + obj->quan * objects[obj->otyp].oc_delay;
  300.             edog->hungrytime =
  301.                 moves + 5*obj->quan * objects[obj->otyp].nutrition;
  302.             mtmp->mconf = 0;
  303.             if(cansee(nix,niy))
  304.                 pline("%s ate %s.", Monnam(mtmp), doname(obj));
  305.             /* perhaps this was a reward */
  306.             if(otyp != CADAVER)
  307.             edog->apport += 200/(edog->dropdist+moves-edog->droptime);
  308.             delobj(obj);
  309.             goto newdogpos;
  310.             }
  311.         nextobj:
  312.             obj = obj->nobj;
  313.         }
  314.  
  315.         for(j=0; j<MTSZ && j<cnt-1; j++)
  316.             if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
  317.                 if(rn2(4*(cnt-j))) goto nxti;
  318.  
  319. /* Some stupid C compilers cannot compute the whole expression at once. */
  320.         nearer = GDIST(nx,ny);
  321.         nearer -= GDIST(nix,niy);
  322.         nearer *= appr;
  323.         if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
  324.             (nearer > 0 && !whappr &&
  325.                 ((omx == nix && omy == niy && !rn2(3))
  326.                 || !rn2(12))
  327.             )){
  328.             nix = nx;
  329.             niy = ny;
  330.             if(nearer < 0) chcnt = 0;
  331.             chi = i;
  332.         }
  333.     nxti:    ;
  334.     }
  335. newdogpos:
  336.     if(nix != omx || niy != omy){
  337.         if(info[chi] & ALLOW_U){
  338.             (void) hitu(mtmp, d(mdat->damn, mdat->damd)+1);
  339.             return(0);
  340.         }
  341.         mtmp->mx = nix;
  342.         mtmp->my = niy;
  343.         for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
  344.         mtmp->mtrack[0].x = omx;
  345.         mtmp->mtrack[0].y = omy;
  346.     }
  347.     if(mintrap(mtmp) == 2)    /* he died */
  348.         return(2);
  349.     pmon(mtmp);
  350.     return(1);
  351. }
  352.  
  353. /* return roomnumber or -1 */
  354. inroom(x,y) xchar x,y; {
  355. #ifndef QUEST
  356.     register struct mkroom *croom = &rooms[0];
  357.     while(croom->hx >= 0){
  358.         if(croom->hx >= x-1 && croom->lx <= x+1 &&
  359.            croom->hy >= y-1 && croom->ly <= y+1)
  360.             return(croom - rooms);
  361.         croom++;
  362.     }
  363. #endif QUEST
  364.     return(-1);    /* not in room or on door */
  365. }
  366.  
  367. tamedog(mtmp, obj)
  368. register struct monst *mtmp;
  369. register struct obj *obj;
  370. {
  371. register struct monst *mtmp2;
  372.     if(mtmp->mtame || mtmp->mfroz ||
  373. #ifndef NOWORM
  374.         mtmp->wormno ||
  375. #endif NOWORM
  376.         mtmp->isshk || mtmp->isgd)
  377.         return(0); /* no tame long worms? */
  378.     if(obj) {
  379.         if(dogfood(obj) >= MANFOOD) return(0);
  380.         if(cansee(mtmp->mx,mtmp->my)){
  381.             pline("%s devours the %s.", Monnam(mtmp),
  382.                 objects[obj->otyp].oc_name);
  383.         }
  384.         obfree(obj, (struct obj *) 0);
  385.     }
  386.     mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
  387.     *mtmp2 = *mtmp;
  388.     mtmp2->mxlth = sizeof(struct edog);
  389.     if(mtmp->mnamelth) (void) strcpy(NAME(mtmp2), NAME(mtmp));
  390.     initedog(mtmp2);
  391.     replmon(mtmp,mtmp2);
  392.     return(1);
  393. }
  394.